package com.uduemc.biso.node.module.service.impl;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.uduemc.biso.core.extities.center.Host;
import com.uduemc.biso.node.core.entities.HRepertory;
import com.uduemc.biso.node.core.entities.SSeoCategory;
import com.uduemc.biso.node.core.utils.SitePathUtil;
import com.uduemc.biso.node.module.mapper.HRepertoryMapper;
import com.uduemc.biso.node.module.service.HRepertoryService;
import com.uduemc.biso.node.module.service.HostService;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

@Service
public class HRepertoryServiceImpl implements HRepertoryService {

	private static final Logger logger = LoggerFactory.getLogger(HRepertoryServiceImpl.class);

	@Autowired
	private HRepertoryMapper hRepertoryMapper;

	@Autowired
	private HostService hostServiceImpl;

	@Override
	public HRepertory insertAndUpdateCreateAt(HRepertory hRepertory) {
		hRepertoryMapper.insert(hRepertory);
		HRepertory findOne = findOne(hRepertory.getId());
		Date createAt = hRepertory.getCreateAt();
		if (createAt != null) {
			hRepertoryMapper.updateCreateAt(findOne.getId(), createAt, HRepertory.class);
		}
		return findOne;
	}

	@Override
	public HRepertory insert(HRepertory hRepertory) {
		hRepertoryMapper.insertSelective(hRepertory);
		return findOne(hRepertory.getId());
	}

	@Override
	public HRepertory insertAllField(HRepertory hRepertory) {
		hRepertoryMapper.insertAllField(hRepertory);
		return findOne(hRepertory.getId());
	}

	@Override
	public HRepertory updateById(HRepertory hRepertory) {
		hRepertoryMapper.updateByPrimaryKeySelective(hRepertory);
		return findOne(hRepertory.getId());
	}

	@Override
	public HRepertory findOne(Long id) {
		return hRepertoryMapper.selectByPrimaryKey(id);
	}

	@Override
	public List<HRepertory> findAll(Pageable pageable) {
		int pageNumber = pageable.getPageNumber();
		int pageSize = pageable.getPageSize();
		PageHelper.startPage(pageNumber, pageSize);
		List<HRepertory> list = hRepertoryMapper.selectAll();
		return list;
	}

	@Override
	public void deleteById(Long id) {
		hRepertoryMapper.deleteByPrimaryKey(id);
	}

	@Override
	public int deleteByHostId(long hostId) {
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		return hRepertoryMapper.deleteByExample(example);
	}

	@Override
	public String getUUIDFilename(long hostId) {
		String substring = UUID.randomUUID().toString().substring(24);

		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("unidname", substring);

		List<HRepertory> selectByExample = hRepertoryMapper.selectByExample(example);
		if (CollectionUtils.isEmpty(selectByExample)) {
			return substring;
		}
		return getUUIDFilename(hostId);
	}

	@Override
	public PageInfo<HRepertory> findByWhereAndPage(long hostId, long labelId, short[] type, short isRefuse, String originalFilename, String[] suffix, int page,
			int size, String sort) {
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		if (labelId >= 0) {
			criteria.andEqualTo("labelId", labelId);
		}
		if (type.length > 0) {
			if (type.length == 1 && type[0] == -1) {

			} else {
				List<Short> types = new ArrayList<>();
				for (short ty : type) {
					types.add(ty);
				}
				criteria.andIn("type", types);
			}
		}
		if (ArrayUtil.isNotEmpty(suffix)) {
			List<String> suffixes = new ArrayList<>();
			for (String sfx : suffix) {
				suffixes.add(sfx);
			}
			criteria.andIn("suffix", suffixes);
		}
		criteria.andEqualTo("isRefuse", isRefuse);
		if (StringUtils.hasText(originalFilename)) {
			String replaceAll = originalFilename.replaceAll("%", "\\\\%").replaceAll("_", "\\\\_");
			criteria.andLike("originalFilename", "%" + replaceAll + "%");
		}
		example.setOrderByClause(sort);
		PageHelper.startPage(page, size);
		List<HRepertory> list = hRepertoryMapper.selectByExample(example);
		PageInfo<HRepertory> pageInfo = new PageInfo<>(list);
		return pageInfo;
	}

	@Override
	@Transactional
	public boolean deleteByList(long[] ids) {
		HRepertory hRepertory = null;
		for (long id : ids) {
			if (id < 1) {
				throw new RuntimeException("数组中包含id小于1的数");
			}
			hRepertory = hRepertoryMapper.selectByPrimaryKey(id);
			if (hRepertory == null) {
				throw new RuntimeException("数据中id为" + id + "不存在");
			}
			if (hRepertory.getIsRefuse().shortValue() == 1) {
				continue;
			}
			hRepertory.setIsRefuse((short) 1);
			if (hRepertoryMapper.updateByPrimaryKeySelective(hRepertory) < 0) {
				throw new RuntimeException("更新数据id:" + id + "的isRefuse出错");
			}
			hRepertory = null;
		}
		return true;
	}

	@Override
	@Transactional
	public boolean reductionByList(long[] ids) {
		HRepertory hRepertory = null;
		for (long id : ids) {
			if (id < 1) {
				throw new RuntimeException("数组中包含id小于1的数");
			}
			hRepertory = hRepertoryMapper.selectByPrimaryKey(id);
			if (hRepertory == null) {
				throw new RuntimeException("数据中id为" + id + "不存在");
			}
			if (hRepertory.getIsRefuse().shortValue() == 0) {
				continue;
			}
			hRepertory.setIsRefuse((short) 0);
			if (hRepertoryMapper.updateByPrimaryKeySelective(hRepertory) < 0) {
				throw new RuntimeException("更新数据id:" + id + "的isRefuse出错");
			}
			hRepertory = null;
		}
		return true;
	}

	@Override
	public boolean reductionAll(long hostId) {
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);

		List<HRepertory> selectByExample = hRepertoryMapper.selectByExample(example);
		if (CollectionUtils.isEmpty(selectByExample)) {
			return true;
		}

		HRepertory hRepertory = new HRepertory();
		hRepertory.setIsRefuse((short) 0);

		int update = hRepertoryMapper.updateByExampleSelective(hRepertory, example);
		return update > 0;
	}

	@Override
	@Transactional
	public boolean clearByList(List<Long> ids, String basePath) {
		HRepertory hRepertory = null;
		for (long id : ids) {
			if (id < 1) {
				throw new RuntimeException("数组中包含id小于1的数");
			}
			hRepertory = hRepertoryMapper.selectByPrimaryKey(id);
			if (hRepertory == null) {
				throw new RuntimeException("数据中id为" + id + "不存在");
			}
			if (hRepertory.getIsRefuse().shortValue() != 1) {
				throw new RuntimeException("数据中id为" + id + ", 要删除的数据不在回收站中。 isRefuse: " + hRepertory.getIsRefuse());
			}
			// 进行彻底删除操作
			boolean clearItem = clearItem(basePath, hRepertory);
			if (!clearItem) {
				throw new RuntimeException("删除文件失败：" + hRepertory.toString());
			}
			hRepertory = null;
		}
		return true;
	}

	@Transactional
	private boolean clearItem(Host host, String basePath, HRepertory hRepertory) {
		if (hRepertory == null || hRepertory.getId() == null || hRepertory.getIsRefuse().shortValue() != 1) {
			throw new RuntimeException("数据 hRepertory 不存在 或者 isRefuse不为1 " + hRepertory);
		}
		if (!StringUtils.hasText(hRepertory.getFilepath())) {
			deleteById(hRepertory.getId());
			return true;
		}
		String userRepertoryPath = SitePathUtil.getUserRepertoryPathByCodeHRepertory(basePath, host.getRandomCode(), hRepertory);
		// 文件是否存在
		if (FileUtil.exist(userRepertoryPath)) {
			boolean del = FileUtil.del(userRepertoryPath);
			if (!del) {
				logger.error("删除文件失败， userRepertoryPath: " + userRepertoryPath);
				throw new RuntimeException("删除文件失败， userRepertoryPath: " + userRepertoryPath);
			}
		}

		String userRepertoryZoompath = SitePathUtil.getUserRepertoryZoompathByCodeHRepertory(basePath, host.getRandomCode(), hRepertory);
		if (StrUtil.isNotBlank(userRepertoryZoompath) && FileUtil.isDirectory(userRepertoryZoompath)) {
			boolean del = FileUtil.del(userRepertoryZoompath);
			if (!del) {
				logger.error("删除文件目录失败， userRepertoryZoompath: " + userRepertoryZoompath);
				throw new RuntimeException("删除文件目录失败， userRepertoryZoompath: " + userRepertoryZoompath);
			}
		}

		// 删除数据
		deleteById(hRepertory.getId());
		return true;
	}

	@Transactional
	private boolean clearItem(String basePath, HRepertory hRepertory) {
		Long hostId = hRepertory.getHostId();
		Host host = hostServiceImpl.findOne(hostId);
		if (host == null) {
			return false;
		}
		return clearItem(host, basePath, hRepertory);
	}

	@Override
	@Transactional
	public boolean clearAll(long hostId, String basePath) {
		Host host = hostServiceImpl.findOne(hostId);
		if (host == null) {
			return false;
		}
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("isRefuse", (short) 1);
		int total = hRepertoryMapper.selectCountByExample(example);
		if (total < 1) {
			return true;
		}

		int pageSize = 20;
		int time = total / pageSize + 1;
		List<HRepertory> selectByExample = null;
		while (true) {
			if (time < 0) {
				return false;
			}

			PageHelper.startPage(1, pageSize);
			selectByExample = hRepertoryMapper.selectByExample(example);
			if (CollectionUtils.isEmpty(selectByExample)) {
				break;
			}
			for (HRepertory hRepertory : selectByExample) {
				if (!clearItem(host, basePath, hRepertory)) {
					throw new RuntimeException("删除文件失败！");
				}
			}

			time--;
		}

		return true;
	}

	@Override
	public boolean existByHostIdAndRepertoryIds(long hostId, List<Long> repertoryIds) {
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andIn("id", repertoryIds);
		int total = hRepertoryMapper.selectCountByExample(example);

		List<Long> ids = new ArrayList<>();
		for (long repertoryId : repertoryIds) {
			if (CollectionUtil.isEmpty(ids)) {
				ids.add(repertoryId);
			} else {
				boolean contains = false;
				for (long id : ids) {
					if (id == repertoryId) {
						contains = true;
					}
				}
				if (!contains) {
					ids.add(repertoryId);
				}
			}

		}
		return ids.size() == total;
	}

	@Override
	public HRepertory findByHostIdAndId(long id, long hostId) {
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("id", id);
		criteria.andEqualTo("hostId", hostId);
		return hRepertoryMapper.selectOneByExample(example);
	}

	@Override
	public boolean existsByOriginalFilenameAndToday(long hostId, LocalDateTime createAt, String originalFilename) {
		// 当天最早的时间以及当前的最晚的时间，通过这段时间来进行排查是否存在
		LocalDateTime first = LocalDateTime.of(createAt.toLocalDate(), LocalTime.MIN);
		LocalDateTime last = LocalDateTime.of(createAt.toLocalDate(), LocalTime.MAX);

		String from = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(first);
		String to = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(last);

		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("originalFilename", originalFilename);
		criteria.andBetween("createAt", from, to);
		List<HRepertory> selectByExample = hRepertoryMapper.selectByExample(example);
		return !CollectionUtils.isEmpty(selectByExample);
	}

	@Override
	public boolean existsByOriginalFilenameAndThisMouth(long hostId, LocalDateTime createAt, String originalFilename) {
		// 当天最早的时间以及当前的最晚的时间，通过这段时间来进行排查是否存在
		LocalDateTime first = LocalDateTime.of(createAt.toLocalDate(), LocalTime.MIN);
		LocalDateTime last = LocalDateTime.of(createAt.toLocalDate(), LocalTime.MAX);

		LocalDateTime firstday = first.with(TemporalAdjusters.firstDayOfMonth());
		LocalDateTime lastDay = last.with(TemporalAdjusters.lastDayOfMonth());

		String from = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(firstday);
		String to = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(lastDay);

		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("originalFilename", originalFilename);
		criteria.andBetween("createAt", from, to);
		List<HRepertory> selectByExample = hRepertoryMapper.selectByExample(example);
		return !CollectionUtils.isEmpty(selectByExample);
	}

	@Override
	public HRepertory findInfoByHostIdFilePath(long hostId, String filePath) {
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("filepath", filePath);
		return hRepertoryMapper.selectOneByExample(example);
	}

	@Override
	public HRepertory findByOriginalFilenameAndToDay(long hostId, long createAt, String originalFilename) {
		Instant instant = Instant.ofEpochMilli(createAt);
		LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
		// 当天最早的时间以及当前的最晚的时间，通过这段时间来进行排查是否存在
		LocalDateTime first = LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MIN);
		LocalDateTime last = LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MAX);

		String firstfrom = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(first);
		String lastto = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(last);

		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("originalFilename", originalFilename);
		criteria.andBetween("createAt", firstfrom, lastto);

		// 存在外链与内部资源重命的情况
		List<HRepertory> selectByExample = hRepertoryMapper.selectByExample(example);
		if (CollUtil.size(selectByExample) == 1) {
			return selectByExample.get(0);
		}
		List<HRepertory> collect = selectByExample.stream().filter(item -> {
			return item.getIsRefuse() == (short) 0;
		}).collect(Collectors.toList());
		if (CollUtil.size(collect) == 1) {
			return collect.get(0);
		}
		List<HRepertory> collect2 = selectByExample.stream().filter(item -> {
			return item.getType() != (short) 4;
		}).collect(Collectors.toList());
		if (CollUtil.size(collect2) == 1) {
			return collect2.get(0);
		}
		return selectByExample.get(0);
	}

	@Override
	public PageInfo<HRepertory> findPageInfoAllByRepertoryQuoteUsed(long hostId, long siteId, int pageNum, int pageSize) {
		PageHelper.startPage(pageNum, pageSize);
		List<HRepertory> listHRepertory = hRepertoryMapper.findPageInfoAllByRepertoryQuoteUsed(hostId, siteId);
		return new PageInfo<>(listHRepertory);
	}

	@Override
	public HRepertory findByOriginalFilenameAndFilepath(long hostId, String originalFilename, String filepath) {
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("originalFilename", originalFilename);
		criteria.andEqualTo("filepath", filepath);
		return hRepertoryMapper.selectOneByExample(example);
	}

	@Override
	public HRepertory findByOriginalFilenameAndLink(long hostId, String originalFilename, String link) {
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("originalFilename", originalFilename);
		criteria.andEqualTo("link", link);
		return hRepertoryMapper.selectOneByExample(example);
	}

	@Override
	public PageInfo<HRepertory> findPageInfoAll(long hostId, int pageNum, int pageSize) {
		Example example = new Example(SSeoCategory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		PageHelper.startPage(pageNum, pageSize);
		List<HRepertory> listHRepertory = hRepertoryMapper.selectByExample(example);
		PageInfo<HRepertory> result = new PageInfo<>(listHRepertory);
		return result;
	}

	@Override
	public int totalType(long hostId, short type) {
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("type", type);
		return hRepertoryMapper.selectCountByExample(example);
	}

	@Override
	public int totalType(long hostId, short type, short isRefuse) {
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("type", type);
		criteria.andEqualTo("isRefuse", isRefuse);
		return hRepertoryMapper.selectCountByExample(example);
	}

	@Override
	public HRepertory findNotCreateByLinkAndHostId(long hostId, String externalLink) {
		if (StrUtil.isBlank(externalLink)) {
			return null;
		}
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		criteria.andEqualTo("type", 4);
		criteria.andEqualTo("link", externalLink);
		List<HRepertory> listHRepertory = hRepertoryMapper.selectByExample(example);
		if (CollectionUtil.isNotEmpty(listHRepertory)) {
			HRepertory hRepertory = listHRepertory.get(0);
			if (hRepertory.getIsRefuse().shortValue() == (short) 1) {
				hRepertory.setIsRefuse((short) 0);
				return updateById(hRepertory);
			} else {
				return hRepertory;
			}
		} else {
			String originalFilename = StrUtil.sub(externalLink, externalLink.lastIndexOf("/") + 1, externalLink.length());
			String suffix = StrUtil.sub(originalFilename, originalFilename.lastIndexOf(".") + 1, originalFilename.length());
			HRepertory hRepertory = new HRepertory();
			hRepertory.setHostId(hostId).setLabelId(0L).setType((short) 4).setOriginalFilename(originalFilename).setLink(externalLink).setSuffix(suffix)
					.setSize(0L).setPixel("0").setIsRefuse((short) 0);
			return insert(hRepertory);
		}
	}

	@Override
	public Map<String, HRepertory> makeExternalLinks(long hostId, List<String> externalLinks) {
		Map<String, HRepertory> result = new HashMap<>();
		for (String link : externalLinks) {
			HRepertory hRepertory = findNotCreateByLinkAndHostId(hostId, link);
			if (hRepertory != null) {
				result.put(link, hRepertory);
			}
		}
		return result;
	}

	@Override
	public List<HRepertory> infosBySslInRsefuse(long hostId) {
		List<HRepertory> listHRepertory = hRepertoryMapper.infosBySslInRsefuse(hostId);
		return listHRepertory;
	}

	@Override
	public List<HRepertory> findInfosByHostIdTypesIds(long hostId, List<Short> types, List<Long> ids) {
		if (CollUtil.isEmpty(ids)) {
			return null;
		}
		Example example = new Example(HRepertory.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("hostId", hostId);
		if (CollUtil.isNotEmpty(types)) {
			criteria.andIn("type", types);
		}
		criteria.andIn("id", ids);
		return hRepertoryMapper.selectByExample(example);
	}

}
